//  -----------------------------------------------------------------------------------------------//
//   This file is part of SvnExternalUpdater                                                               //
//   Copyright (C)2008 Romain Verdier ( romain@codingly.com )                                      //
//                                                                                                 //
//   This program is free software; you can redistribute it and/or modify it under the terms       //
//   of the GNU General Public License as published by the Free Software Foundation; either        //
//   version 2 of the License, or (at your option) any later version. This program is distributed  //
//   in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied        //
//   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public  //
//   License for more details.                                                                     //
//                                                                                                 //
//   You should have received a copy of the GNU General Public License along with this program; if //
//   not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. or  //
//   see http://www.fsf.org/licensing/licenses/gpl.html                                            //
//  -----------------------------------------------------------------------------------------------//
using System;
using System.Collections.Generic;
using Codingly.SvnExternalUpdater.Core.EventHandlers;
using Codingly.SvnExternalUpdater.Core.Model;
using Codingly.SvnExternalUpdater.Core.Services;
using Codingly.SvnExternalUpdater.Model;
using Codingly.SvnExternalUpdater.Mvp;
using Codingly.SvnExternalUpdater.Services;
using Codingly.SvnExternalUpdater.Views;

namespace Codingly.SvnExternalUpdater.Presenters
{
	public class MainPresenter : AbstractPresenter<IMainView, MainPresenter>
	{
		private readonly IConfigurationService configurationService;
		private readonly IMonitoringService monitoringService;
		private readonly IPresenterProvider presenterProvider;

		private readonly Dictionary<IProject, ProjectPresenter> presenters = new Dictionary<IProject, ProjectPresenter>();

		private MonitorConfiguration configuration;

		public MainPresenter(IPresenterProvider presenterProvider, IConfigurationService configurationService, IMonitoringService monitoringService)
		{
			this.presenterProvider = presenterProvider;
			this.configurationService = configurationService;
			this.monitoringService = monitoringService;
			this.monitoringService.ExternalStatusChanged += monitor_ExternalStatusChanged;
			this.monitoringService.ProjectStatusChanged += monitor_ProjectStatusChanged;
			this.monitoringService.ProjectAdded += monitor_ProjectAdded;
			this.monitoringService.ProjectRemoved += monitor_ProjectRemoved;
			this.monitoringService.UpdateStarted += monitor_UpdateStarted;
			this.monitoringService.UpdateStopped += monitor_UpdateStopped;
		}

		public void ConfigureMonitoredProjects()
		{
			var configurationPresenter = this.presenterProvider.Get<ConfigurationPresenter>();

			configurationPresenter.Execute();

			if (configurationPresenter.ConfigurationWasModified)
			{
				this.monitoringService.Stop();
				this.configuration = configurationPresenter.Configuration;
				this.monitoringService.Configure(this.configuration.Projects, this.configuration.Interval);
				this.monitoringService.Start();
			}
		}

		public void Refresh()
		{
			this.monitoringService.Refresh();
		}

		public void ShowAbout()
		{
			this.monitoringService.Stop();
			var aboutPresenter = this.presenterProvider.Get<AboutPresenter>();
			aboutPresenter.Execute();
			this.monitoringService.Start();
		}

		public void Start()
		{
			this.view.PlaceHolderKey = typeof (MainPresenter).Name;
			LoadConfiguration();
			StartApplication();
			this.monitoringService.Start();
		}

		public void Stop()
		{
			this.monitoringService.Stop();
		}

		private void LoadConfiguration()
		{
			this.configuration = this.configurationService.GetConfiguration();
			this.monitoringService.Configure(this.configuration.Projects, this.configuration.Interval);
		}

		private void StartApplication()
		{
			this.view.Run();
		}

		private void monitor_ExternalStatusChanged(object sender, StatusChangedEventArgs args)
		{
			this.view.ExternalsAreUpToDate = args.IsUpToDate;
		}

		private void monitor_ProjectAdded(object sender, ProjectEventArgs args)
		{
			var presenter = this.presenterProvider.Get<ProjectPresenter>();
			presenter.Start(args.Project, this.view.PlaceHolderKey);
			this.presenters.Add(args.Project, presenter);
		}

		private void monitor_ProjectRemoved(object sender, ProjectEventArgs args)
		{
			ProjectPresenter presenter;
			if (this.presenters.TryGetValue(args.Project, out presenter))
			{
				presenter.Stop();
				this.presenters.Remove(args.Project);
			}
		}

		private void monitor_ProjectStatusChanged(object sender, StatusChangedEventArgs args)
		{
			this.view.ProjectsAreUpToDate = args.IsUpToDate;
		}

		private void monitor_UpdateStarted(object sender, EventArgs e)
		{
			this.view.BeginUpdate();
		}

		private void monitor_UpdateStopped(object sender, EventArgs e)
		{
			this.view.EndUpdate();
		}
	}
}